

#include "ch32v30x.h"
#include "usbd_core.h"
#include "usb_config.h"
#include "stdio.h"
#include "string.h"
#include "rtthread.h"
#include "rtdevice.h"
#include "board.h"


void my_delay(uint32_t time)
{
    uint32_t count = 0;
    while(time--)
    {
        count = 0;
        while(count < 1200)
        {
            count++;
        }
    }
}

void usb_dc_low_level_init(void)
{

    RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY);
    RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
    RCC_USBHSConfig(RCC_USBPLL_Div2);
    RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M);
    RCC_USBHSPHYPLLALIVEcmd(ENABLE);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
    NVIC_EnableIRQ( USBHS_IRQn );

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE);
    //EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
    NVIC_EnableIRQ(OTG_FS_IRQn);

    my_delay(200);
    rt_kprintf("usbd init\n");
    //rt_thread_mdelay(2);
    //Delay_Us(100);
}



void cdc_acm_init(void);



int cdc_acm_data_write(uint8_t *buffer, uint16_t len);
int cdc_acm_data_read(uint8_t *buffer, uint16_t len);
int cdc_acm_data_wait(int32_t timeout);


int cdc_acm_data_read_wait(uint8_t *buffer, uint16_t len, int32_t byte_timeout, int32_t frame_timeout)
{
    uint16_t    read_pos = 0;
    int32_t     wait_time = 0;
    int32_t     rc = 0;

    do
    {
        rc = cdc_acm_data_read( buffer + read_pos, len - read_pos);
        if(rc < 0)
        {
            goto __fail_exit;
        }else if (rc == 0)
        {
            wait_time = frame_timeout;
        }else
        {
            wait_time = byte_timeout;
        }
        read_pos += rc;
        if (read_pos >= len)
        {
            break; // read ok
        }
        rc = cdc_acm_data_wait(wait_time);
    } while (rc == RT_EOK);

    return read_pos;

    __fail_exit:
    return rc; // happen An error occurred
}




uint8_t buffer[256] = {0};

static void app_usb_thread(void *param)
{
    rt_thread_mdelay(100);
    cdc_acm_init();

    //int rc = 0;
    int len = 0;


    rt_kprintf("timer %p\n", rt_thread_self()->thread_timer);

    //rt_timer_detach
    while(1)
    {
//        rt_thread_mdelay(1000);
//        rc =  cdc_acm_data_wait(RT_WAITING_FOREVER);
//        if(rc == RT_EOK)
//        {
//            rt_kprintf("cdc wait:%d\n",rc);
//            len = cdc_acm_data_read(buffer, 256);
//        }
        len = cdc_acm_data_read_wait(buffer, 256, 10, 10000);
        if(len > 0)
        {
            rt_kprintf("cdc rx:%d\n",len);
            cdc_acm_data_write(buffer, len);
        }

    }
}


void app_usb_init(void)
{
    static int usb_init = 0;
    rt_thread_t tid;
    if(usb_init > 0)
    {
        return;
    }
    usb_init = 1;

    tid = rt_thread_create("app usb",app_usb_thread, NULL,4096,19, 10);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
}

